package com.type.TypingDetector;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;

public class DataVisualization extends Activity {
	public static final String TYPE = "type";
	private XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();
	//private XYMultipleSeriesDataset mDataset2 = new XYMultipleSeriesDataset();
	private XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
	private XYSeries mCurrentSeries;
	private XYSeries[] seriesArray;
	private XYSeriesRenderer mCurrentRenderer;
	private XYSeriesRenderer[] rendererArray;
	private String mDateFormat;
	private GraphicalView mChartView;
	//private GraphicalView mChartView2;
	private long time;
	private boolean first=true;
	private SensorManager sm;
    private List<Sensor> sensors;
    private Sensor accel;
    private int counter;
    double[][][] sVals; //5 is the number of different types of data, 512 is the samples
    String[] seriesTitle; //= {"Phone Detached", "Sitting/Standing", "Walking", "Running", "Jumping", "Stairs Up", "Stairs Down", "Bus"};
    private int smoothIterations=0;
    private boolean[] display;
    private ListView lv;
    private DataVisAdapter dvAdapter;
    private Random generator;
    private final String PATH_TO_FILE="data/data/com.type.TypingDetector";
    private final String FOLDER_NAME="SavedFiles";
    private final int LAST_HARDCODED_INDEX=6;
    private int lastPos=-1;
    
  //Database stuff
    protected final String DATABASE_TABLE="AccelValues3";
    protected final String FN_TABLE="Filenames3";
    protected ArrayList<String> colNames= new ArrayList<String>(Arrays.asList("Title", "XDom", "XAvg", "XMax", "XMin", "YDom", "YAvg", "YMax", "YMin", "ZDom", "ZAvg", "ZMax", "ZMin", "Filename"));
    protected ArrayList<String> colOpts= new ArrayList<String>(Arrays.asList("text","real","real","real","real","real","real","real","real","real","real","real","real", "text"));
    protected ArrayList<String> rowNames; //new ArrayList<String>(Arrays.asList("Phone Detached", "Idle", "Walking", "Running", "Jumping"));
    protected ArrayList<String> rowFileNames= new ArrayList<String>();
    protected ArrayList<String> rowFileTypes= new ArrayList<String>();
    protected ArrayList<String> fileNames;//= new ArrayList<String>(Arrays.asList("tabletopnew.txt", "sittingnew.txt", "walkingnewb.txt", "runningnewb.txt", "jumpingnewb.txt"));
    protected ArrayList<String> fntbColNames = new ArrayList<String>(Arrays.asList("Type","Filename"));
    protected ArrayList<String> fntbColOpts = new ArrayList<String>(Arrays.asList("text","text"));
    private DatabaseQuery query, fnQuery;
    
    /** This is a hacked workaround to keep the accelerometer active even while the screen is off
     * 
     * @param mReciever - A broadcast reciever which recieves the intent ACTION_SCREEN_OFF. Registered in onCreate. 
     */
    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
    	public void onReceive(Context context, Intent intent) {
    		if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
    			sm.unregisterListener(mySEL);
    			sm.registerListener(mySEL, accel, SensorManager.SENSOR_DELAY_GAME);
    			}
    		}
    	};
    	
    /** This method restores important data to the Activity if it is killed by the system and restarted
         * More information available in Android Docs.
         * @param savedState - The saved values set by onSaveInstanceState	
    */	
	@Override
	  protected void onRestoreInstanceState(Bundle savedState) {
	    super.onRestoreInstanceState(savedState);
	    mDataset = (XYMultipleSeriesDataset) savedState.getSerializable("dataset");
	    mRenderer = (XYMultipleSeriesRenderer) savedState.getSerializable("renderer");
	    mCurrentSeries = (XYSeries) savedState.getSerializable("current_series");
	    mCurrentRenderer = (XYSeriesRenderer) savedState.getSerializable("current_renderer");
	    mDateFormat = savedState.getString("date_format");
	    //sm = (SensorManager) savedState.getSerializable("SensorManager");
	    first=savedState.getBoolean("first");
	    time=savedState.getLong("time");
	    counter=savedState.getInt("counter");
	    //mCurrentSeries.clear();
	    //counter=0;
	  }

	 /** This method saves important data if the system kills Activity forcefully, such as when orientation is changed
     * More information available in Android Docs.
     */
	  @Override
	  protected void onSaveInstanceState(Bundle outState) {
	    super.onSaveInstanceState(outState);
	    outState.putSerializable("dataset", mDataset);
	    outState.putSerializable("renderer", mRenderer);
	    outState.putSerializable("current_series", mCurrentSeries);
	    outState.putSerializable("current_renderer", mCurrentRenderer);
	    outState.putString("date_format", mDateFormat);
	    outState.putInt("counter", counter);
	    outState.putLong("time", time);
	    //outState.putSerializable(key, value);
	    outState.putBoolean("first", first);
	  }
	  
	  /** This method creates the layout of the Activity and initializes most global variables and sensors.
	     * If onRestoreInstanceState was called before this method (meaning this is not the first time the Activity has been
	     * opened, then the variable initializations are bypassed, and only the sensors are initialized.
	     */
	  @Override
	  protected void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.xy_chartb);
	    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
	    final VisualizationDataObject data = (VisualizationDataObject) getLastNonConfigurationInstance();
	    
	    if (query==null) query=new DatabaseQuery(this, colNames, colOpts, DATABASE_TABLE);
		if (fnQuery==null) fnQuery=new DatabaseQuery(this, fntbColNames, fntbColOpts, FN_TABLE);
		fileNames=fnQuery.getDataNS(new String[] {"Filename"}, null, null, null, null);
		ArrayList<String> titles=fnQuery.getDataNS(new String[] {"Type"}, null, null, null, null);
		sVals=new double[fileNames.size()][512][3];
		seriesTitle=fileNames.toArray(new String[fileNames.size()]);
		/*seriesTitle=new String[titles.size()];
		for(int j=0; j<seriesTitle.length; j++) {
			seriesTitle[j]=titles.get(j);
		}*/
		display=new boolean[fileNames.size()];
		for (int j=0; j<display.length; j++) display[j]=false;
		generator=new Random(5);
		String[] fn=fileNames.toArray(new String[fileNames.size()]);
		
	    if (mCurrentRenderer==null) {
	    	//String[] seriesTitle = {"Phone Detached", "Sitting/Standing", "Walking", "Running", "Jumping"};
	    	//int[] colors = {Color.GREEN, Color.BLUE, Color.RED, Color.CYAN, Color.WHITE, Color.DKGRAY, Color.MAGENTA, Color.LTGRAY};
	    	int[] colors=new int[6];
	    	for (int k=0; k<colors.length; k++) {
	    		colors[k]=Color.rgb(generator.nextInt(255), generator.nextInt(255), generator.nextInt(255));
	    	}
	    	//String[] fileNames = {"tabletopnew.txt", "sittingnew.txt", "walkingnewb.txt", "runningnewb.txt", "jumpingnewb.txt"};
	    	
	    	XYSeries series; //new XYSeries(seriesTitle);
	    	
	    	if (data!=null) {
	    		seriesArray = (XYSeries[])data.getSeriesArray();
	    		rendererArray = (XYSeriesRenderer[])data.getRendererArray();
	    	}
	    	else {
	    		seriesArray = new XYSeries[seriesTitle.length*3];
	    		rendererArray = new XYSeriesRenderer[colors.length];
	    		for (int i=0; i <seriesArray.length; i+=3) {
	    			series=new XYSeries(seriesTitle[i/3]+" X");
	    			seriesArray[i]=series;
	    			series=new XYSeries(seriesTitle[i/3]+" Y");
	    			seriesArray[i+1]=series;
	    			series=new XYSeries(seriesTitle[i/3]+" Z");
	    			seriesArray[i+2]=series;
	    			//mDataset.addSeries(series);
	    			if (i<colors.length) {
	    				XYSeriesRenderer renderer = new XYSeriesRenderer();
	    				renderer.setLineWidth(2.0f);
	    				renderer.setColor(colors[i]);
	    				rendererArray[i] = renderer;
	    			}
	    		}
	    	}
	    	
	    	/*XYSeriesRenderer renderer = new XYSeriesRenderer();
	    	renderer.setLineWidth(2.0f);
	    	mRenderer.addSeriesRenderer(renderer);
	    	mCurrentRenderer=renderer;*/
	    	
	    	try {
	    		plotFiles(fn,colors);
	    	}
			catch (IOException e) {
				//diffText.setText("meh");
			}
			
			//ArrayList<String> listNames=fnQuery.getDataNS(new String[] {"Type"}, null, null, null, null);
			lv=(ListView) findViewById(R.id.listV);
			dvAdapter=new DataVisAdapter(this,
	                R.layout.vislist, fileNames);
			lv.setAdapter(dvAdapter);
			lv.setTextFilterEnabled(true);
			lv.setOnItemClickListener(listLstnr);
			
			
			series=new XYSeries("Current Data X");
			mDataset.addSeries(series);
			mRenderer.addSeriesRenderer(rendererArray[0]);
			series=new XYSeries("Current Data Y");
			mDataset.addSeries(series);
			mRenderer.addSeriesRenderer(rendererArray[1]);
			series=new XYSeries("Current Data Z");
			mDataset.addSeries(series);
			mRenderer.addSeriesRenderer(rendererArray[2]);
			mCurrentSeries = series;
			mCurrentRenderer = rendererArray[2];
	    	//mRenderer.setXAxisMax(512);
	    	counter=0;
	    }	
	    
	    //mCurrentSeries.clear();
	    Spinner spinner = (Spinner) findViewById(R.id.spinner);
	    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
	            this, R.array.smooth_vals, android.R.layout.simple_spinner_item);
	    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	    spinner.setAdapter(adapter);
	    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
	    
	    registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
	    sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
	    sensors = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);
        
	    if (sensors.size() > 0) {
	    	accel = sensors.get(0);
	    }
        //sm.registerListener(mySEL, accel, SensorManager.SENSOR_DELAY_GAME);
        if(time==0) {time=SystemClock.uptimeMillis();}
	 }
	  
	  /** Called if the activity is paused and then reopened
		 * 
		 */
	  protected void onResume() {
		    super.onResume();
		    if (mChartView == null) {
		      LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
		      mChartView = ChartFactory.getLineChartView(this, mDataset, mRenderer);
		      //mChartView2 = ChartFactory.getLineChartView(this, mDataset2, mRenderer);
		      layout.addView(mChartView, new LayoutParams(LayoutParams.FILL_PARENT,
		          LayoutParams.FILL_PARENT));
		      //layout.addView(mChartView2, new LayoutParams(LayoutParams.FILL_PARENT,
			          //LayoutParams.FILL_PARENT));
		      //boolean enabled = mDataset.getSeriesCount() > 0;
		      //setSeriesEnabled(enabled);
		    } else {
		      mChartView.repaint();
		    }
	}
	  
	  /** Plots files passed in.
	   * 
	   * @param fileNames array of file names which point to the files containing the point data
	   * @param colors array of colors which should be the same size as fileNames
	   * @throws IOException
	   */
	private void plotFiles(String[] fileNames, int[] colors) throws IOException {
		Scanner scan;
		//AssetManager am = getAssets();
		
		for (int i=0; i<seriesTitle.length; i++) {
			//mCurrentSeries = mDataset.getSeriesAt(i);
	    	scan=new Scanner(new File(PATH_TO_FILE + "/" + FOLDER_NAME + "/" + fileNames[i]));
	    	
	    	int ctr=0;
	    	//double[] sVals=new double[512];
	    	scan.nextLine();
	    	while (scan.hasNextLine()) { //must be formatted as xval, yval, zval
				String temp=scan.nextLine();
				
				if (temp!="") {
					String[] tmp=temp.split(",");
					double storValX = Double.valueOf(tmp[0]);
					double storValY = Double.valueOf(tmp[1]);
					double storValZ = Double.valueOf(tmp[2]);
					if (ctr < sVals[i].length) 
					{
						sVals[i][ctr][0]=storValX;
						sVals[i][ctr][1]=storValY;
						sVals[i][ctr][2]=storValZ;
						//mCurrentSeries.add(ctr, storVal);
					}
					ctr++;
				}
			}
	    	scan.close();
		}
	}
	
	/** Plots of unplots the checked/unchecked values.
	 * 
	 */
	/*private OnClickListener lstnr = new OnClickListener() {
	    public void onClick(View v) {
	        // Perform action on clicks, depending on whether it's now checked
	    	int index=getIndexOfCB(v.getId());
	    	if (((CheckBox) v).isChecked()) {
	        	XYSeriesRenderer temp=mCurrentRenderer;
	        	//mCurrentRenderer=(XYSeriesRenderer)mRenderer.getSeriesRendererAt(index);
	        	if (index != -1) {
	        		mCurrentRenderer=rendererArray[index];
	        		mRenderer.addSeriesRenderer(mCurrentRenderer);
	        		XYSeries curr=seriesArray[index];
	        		curr.clear();
	        		double[] tmp=sVals[index];
		    		for (int j=0; j<smoothIterations; j++) {
		    			tmp=AcceleromterUpdated.smoothValues(tmp);
		    		}
		    		for (int j=0; j<tmp.length; j++) {
	    				curr.add(j, tmp[j]);
	    			}
	        		mDataset.addSeries(curr);
	        		mCurrentRenderer=temp;
	        	}
	        } else {
	        	mDataset.removeSeries(seriesArray[index]);
	        	//mRenderer.removeSeriesRenderer(rendererArray[findRendererIndex(seriesArray[index])]);
	        	mRenderer.removeSeriesRenderer(rendererArray[index]);
	        }
	    	if (mChartView != null) {
		          mChartView.repaint();
		    }
	    }
	};*/
	
	/** Plots of unplots the checked/unchecked values.
	 * 
	 */
	private OnItemClickListener listLstnr = new OnItemClickListener() {
		public void onItemClick(AdapterView<?> parent, View view,
		        int position, long id) {
	        // Perform action on clicks, depending on whether it's now checked
	    	//int index=getIndexOfCB(v.getId());
			if (lastPos!=-1 && lastPos!=position) {
				mDataset.removeSeries(seriesArray[lastPos]);
				mDataset.removeSeries(seriesArray[lastPos+1]);
				mDataset.removeSeries(seriesArray[lastPos+2]);
				display[lastPos]=!display[lastPos];
				lastPos=position;
			}

			display[position] = !display[position];
	    	if (display[position]) {
	        	XYSeriesRenderer temp=mCurrentRenderer;
	        	//mCurrentRenderer=(XYSeriesRenderer)mRenderer.getSeriesRendererAt(index);
	        	
	        	mCurrentRenderer=rendererArray[3];
	        	mRenderer.addSeriesRenderer(mCurrentRenderer);
	        	XYSeries curr=seriesArray[position];
	        	curr.clear();
	        	double[] tmp=sVals[position][0];
		    	for (int j=0; j<smoothIterations; j++) {
		    		tmp=AcceleromterUpdated.smoothValues(tmp);
		    	}
		    	for (int j=0; j<tmp.length; j++) {
	    			curr.add(j, tmp[j]);
	    		}
		    	
		    	mCurrentRenderer=rendererArray[4];
	        	mRenderer.addSeriesRenderer(mCurrentRenderer);
	        	curr=seriesArray[position+1];
	        	curr.clear();
	        	tmp=sVals[position][1];
		    	for (int j=0; j<smoothIterations; j++) {
		    		tmp=AcceleromterUpdated.smoothValues(tmp);
		    	}
		    	for (int j=0; j<tmp.length; j++) {
	    			curr.add(j, tmp[j]);
	    		}
	        	mDataset.addSeries(curr);
	        	
	        	mCurrentRenderer=rendererArray[5];
	        	mRenderer.addSeriesRenderer(mCurrentRenderer);
	        	curr=seriesArray[position+2];
	        	curr.clear();
	        	tmp=sVals[position][2];
		    	for (int j=0; j<smoothIterations; j++) {
		    		tmp=AcceleromterUpdated.smoothValues(tmp);
		    	}
		    	for (int j=0; j<tmp.length; j++) {
	    			curr.add(j, tmp[j]);
	    		}
		    	
	        	mDataset.addSeries(curr);
	        	mCurrentRenderer=temp;
	        }
	        else {
	        	for (int i=0; i<3; i++) {
	        		mDataset.removeSeries(seriesArray[lastPos+i]);
	        		mRenderer.removeSeriesRenderer(rendererArray[3+i]);
	        	}
	        	//mRenderer.removeSeriesRenderer(rendererArray[findRendererIndex(seriesArray[index])]);
	        	
	        }
	    	
	    	if (lastPos==position) {
				lastPos=-1;
			}
			else {
				lastPos=position;
			}
	    	
	    	if (mChartView != null) {
		          mChartView.repaint();
		    }
	    	dvAdapter.notifyDataSetChanged();
	    }
	};
	
	/** Finds the index of the given series within the XYMultipleDataSeries.
	 * 
	 * @param series the series sought
	 * @return the index of the series passed in
	 */
	private int findRendererIndex(XYSeries series) {
		XYSeries[] temp = mDataset.getSeries();
		for (int i=0; i<temp.length; i++) {
			if (series==temp[i]) {
				return i;
			}
		}
		return 0;
	}
	
	/** Returns the index of the checkbox specified by the ID passed in.
	 * 
	 * @param input the ID of the checkbox
	 * @return the corresponding index
	 */
	/*private int getIndexOfCB(int input) {
		
		switch (input) {
			case R.id.cb1:
				return 0;
			case R.id.cb2:
				return 1;
			case R.id.cb3:
				return 2;
			case R.id.cb4:
				return 3;
			case R.id.cb5:
				return 4;
		}
		return -1;
	}*/
	
	/** The SensorEventListener for the accelerometer. Called whenever the sensor values are changed.
	 * 
	 */
	private final SensorEventListener mySEL = new SensorEventListener() {
		/** First converts the three sensor values into one via Pythagorean theorem, then plots this point against
		 * a tracked counter.
		 * 
		 * @param event - The event values
		 */
		public void onSensorChanged(SensorEvent event) {
			double val=Math.sqrt(Math.pow(event.values[0],2) + Math.pow(event.values[1],2) + Math.pow(event.values[2],2));	
				//displayAccelValues(dataArr[counter]);
				/*if (counter>=512) {
					mCurrentSeries.remove(0);	
				}
				else {
					counter++;
				}*/
				
				
				/*if (!first) {
					mCurrentSeries.remove(0);
				}*/
				
				long xVal=(SystemClock.uptimeMillis()-time)%512;
				for (int i=0; i<event.values.length; i++) {
					mCurrentSeries=mDataset.getSeriesAt(i);
					mCurrentRenderer=(XYSeriesRenderer) mRenderer.getSeriesRendererAt(i);
					mCurrentSeries.add(counter, event.values[i]);
				}
				
				if (counter>=511) {
					mDataset.getSeriesAt(0).clear();
					mDataset.getSeriesAt(1).clear();
					mDataset.getSeriesAt(2).clear();
					//counter=0;
				}
				
				if (mChartView != null) {
			          mChartView.repaint();
			    }
				
				counter++;
				counter%=512;
		}
		
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
			
		}
	};
	
	/** Saves data which needs to be retained when application is destroyed. Differs from onSaveInstanceState
	 * and onRestoreInstanceState() in that this data does not need to be Serializable, and is simply stored as 
	 * an instance of Object. Requires self-wrote class to save the data
	 * 
	 */
	@Override
	public Object onRetainNonConfigurationInstance() {
	    final VisualizationDataObject data = new VisualizationDataObject(seriesArray, rendererArray);
	    return data;
	}
	
	/** Spinner OnClickListener.
	 * 
	 * @author Sauvik Das
	 *
	 */
	public class MyOnItemSelectedListener implements OnItemSelectedListener {
		
		/** Smooths values off static series based on selection
		 * 
		 */
	    public void onItemSelected(AdapterView<?> parent,
	        View view, int pos, long id) {
	    	int noSmooth=Integer.valueOf(parent.getItemAtPosition(pos).toString());
	    	smoothIterations=noSmooth;
	    	int addCount=0;
	    	for (int i=0; i<display.length; i++) {
	    		if (display[i]) {
	    			double[] tempX=sVals[i][0];
	    			double[] tempY=sVals[i][1];
	    			double[] tempZ=sVals[i][2];
	    			for (int j=0; j<noSmooth; j++) {
	    				tempX=AcceleromterUpdated.smoothValues(tempX);
	    				tempY=AcceleromterUpdated.smoothValues(tempY);
	    				tempZ=AcceleromterUpdated.smoothValues(tempZ);
	    			}
	    			for (int j=0; j<3; j++) {
	    				XYSeries curr=mDataset.getSeriesAt(3+j);
	    				curr.clear();
	    				for (int k=0; k<tempX.length; j++) {
		    				if (j==0) curr.add(k, tempX[k]);
		    				if (j==1) curr.add(k, tempY[k]);
		    				if (j==2) curr.add(k, tempZ[k]);
		    			}
	    			}
	    		/*if (findRightIndex(i)>=0) {
	    			XYSeries curr = mDataset.getSeriesAt(findRightIndex(i));
	    			curr.clear();
	    			for (int j=0; j<temp.length; j++) {
	    				curr.add(j, temp[j]);
	    			}
	    		}*/
	    		}
	    	}
	    	
	    	if (mChartView != null) {
		          mChartView.repaint();
		    }
	      /*Toast.makeText(parent.getContext()), "The planet is " +
	          parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();*/
	    }

	    public void onNothingSelected(AdapterView parent) {
	      // Do nothing.
	    }
	    
	    public int findRightIndex(int ind) {
	    	String find=seriesTitle[ind]; //seriesTitle and sVals have to be in the same order
	    	for (int i=0; i<mDataset.getSeriesCount();i++) {
	    		if (mDataset.getSeriesAt(i).getTitle().equalsIgnoreCase(find)) {
	    			return i;
	    		}
	    	}
	    	return -1;
	    }
	}
	
	/** The adapter given to display the List of predicted activities
	 * 
	 * @author Sauvik Das
	 *
	 */
	private class DataVisAdapter extends ArrayAdapter<String> {

	    private ArrayList<String> items;

	    public DataVisAdapter(Context context, int textViewResourceId, ArrayList<String> items) {
	            super(context, textViewResourceId, items);
	            this.items = items;
	    }
	    
	    @Override
	    public View getView(int position, View convertView, ViewGroup parent) {
	            View v = convertView;
	            if (v == null) {
	                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	                v = vi.inflate(R.layout.vislist, null);
	            }
	            String o = items.get(position);
	            if (o != null) {
	                    TextView tt = (TextView) v.findViewById(R.id.listViewText);
	                    if (tt != null) {
	                    	if (display[position]) {
	                    		tt.setTextColor(Color.GREEN);
	                    	}
	                    	else {
	                    		tt.setTextColor(Color.RED);
	                    	}
	                        tt.setText(o);}
	            }
	            return v;
	    }
	}
}
